package org.linlinjava.litemall.db.service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.annotation.Resource;

import org.beetl.sql.core.query.LambdaQuery;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.mapper.LitemallOrderDao;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class LitemallOrderService {
    @Resource
    private LitemallOrderDao litemallOrderDao;
	/*
	 * @Resource private OrderMapper orderMapper;
	 */

    public int add(LitemallOrder order) {
        order.setAddTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        litemallOrderDao.insertTemplate(order,true);
        return 1;
        //return litemallOrderMapper.insertSelective(order);
    }

    public int count(Integer userId) {
    	LitemallOrder order = new LitemallOrder();
    	order.setUserId(userId);
    	order.setDeleted(false);
    	return (int)litemallOrderDao.templateCount(order);
    	
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andUserIdEqualTo(userId).andDeletedEqualTo(false); return (int)
		 * litemallOrderMapper.countByExample(example);
		 */
    }

    public LitemallOrder findById(Integer orderId) {
    	return litemallOrderDao.single(orderId);
        //return litemallOrderMapper.selectByPrimaryKey(orderId);
    }

    public LitemallOrder findById(Integer userId, Integer orderId) {
    	
    	LitemallOrder order= new LitemallOrder();
    	order.setUserId(userId);
    	order.setId(orderId);
    	order.setDeleted(false);
    	return litemallOrderDao.templateOne(order);
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andIdEqualTo(orderId).andUserIdEqualTo(userId).andDeletedEqualTo
		 * (false); return litemallOrderMapper.selectOneByExample(example);
		 */
    }

    private String getRandomNum(Integer num) {
        String base = "0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < num; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public int countByOrderSn(Integer userId, String orderSn) {
    	
    	LitemallOrder order= new LitemallOrder();
    	order.setUserId(userId);
    	order.setOrderSn(orderSn);
    	order.setDeleted(false);
    	return (int)litemallOrderDao.templateCount(order);
    	
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andUserIdEqualTo(userId).andOrderSnEqualTo(orderSn).
		 * andDeletedEqualTo(false); return (int)
		 * litemallOrderMapper.countByExample(example);
		 */
    }

    // TODO 这里应该产生一个唯一的订单，但是实际上这里仍然存在两个订单相同的可能性
    public String generateOrderSn(Integer userId) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
        String now = df.format(LocalDate.now());
        String orderSn = now + getRandomNum(6);
        while (countByOrderSn(userId, orderSn) != 0) {
            orderSn = now + getRandomNum(6);
        }
        return orderSn;
    }

    public List<LitemallOrder> queryByOrderStatus(Integer userId, List<Short> orderStatus, Integer page, Integer limit, String sort, String order) {
    	LambdaQuery<LitemallOrder> query = litemallOrderDao.createLambdaQuery();
    	 query.andEq(LitemallOrder::getUserId, userId);
    	if (orderStatus != null) {
  		  query.andIn(LitemallOrder::getOrderStatus, orderStatus);
        }
        query.andEq(LitemallOrder::getDeleted, false);
        query.orderBy(LitemallOrder.Column.addTime.desc());
        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
      	  query.orderBy(sort + " " + order);
        }
        query.limit(page, limit);
        return query.select();
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.setOrderByClause(LitemallOrder.Column.addTime.desc());
		 * LitemallOrderExample.Criteria criteria = example.or();
		 * criteria.andUserIdEqualTo(userId); if (orderStatus != null) {
		 * criteria.andOrderStatusIn(orderStatus); } criteria.andDeletedEqualTo(false);
		 * if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
		 * example.setOrderByClause(sort + " " + order); }
		 * 
		 * PageHelper.startPage(page, limit); return
		 * litemallOrderMapper.selectByExample(example);
		 */
    }

    public List<LitemallOrder> querySelective(Integer userId, String orderSn, LocalDateTime start, LocalDateTime end, List<Short> orderStatusArray, Integer page, Integer limit, String sort, String order) {
    	
    	LambdaQuery<LitemallOrder> query = litemallOrderDao.createLambdaQuery();
    	if (userId != null) {
    		query.andEq(LitemallOrder::getUserId, userId);
        }
        if (!StringUtils.isEmpty(orderSn)) {
        	query.andEq(LitemallOrder::getOrderSn, orderSn);
        }
        if(start != null){
        	query.andGreat(LitemallOrder::getAddTime, start);
        }
        if(end != null){
        	query.andLess(LitemallOrder::getAddTime, end);
        }
        if (orderStatusArray != null && orderStatusArray.size() != 0) {
        	query.andIn(LitemallOrder::getOrderStatus, orderStatusArray);
        }
        query.andEq(LitemallOrder::getDeleted, false);

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
        	query.orderBy(sort + " " + order);
        }
       query.limit(page, limit);
       return query.select();
    	
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * LitemallOrderExample.Criteria criteria = example.createCriteria();
		 * 
		 * if (userId != null) { criteria.andUserIdEqualTo(userId); } if
		 * (!StringUtils.isEmpty(orderSn)) { criteria.andOrderSnEqualTo(orderSn); }
		 * if(start != null){ criteria.andAddTimeGreaterThanOrEqualTo(start); } if(end
		 * != null){ criteria.andAddTimeLessThanOrEqualTo(end); } if (orderStatusArray
		 * != null && orderStatusArray.size() != 0) {
		 * criteria.andOrderStatusIn(orderStatusArray); }
		 * criteria.andDeletedEqualTo(false);
		 * 
		 * if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
		 * example.setOrderByClause(sort + " " + order); }
		 * 
		 * PageHelper.startPage(page, limit); return
		 * litemallOrderMapper.selectByExample(example);
		 */
    }

    public int updateWithOptimisticLocker(LitemallOrder order) {
        LocalDateTime preUpdateTime = order.getUpdateTime();
        order.setUpdateTime(LocalDateTime.now());

        LambdaQuery<LitemallOrder> query = litemallOrderDao.createLambdaQuery();
        query.andEq(LitemallOrder::getId, order.getId());
        query.andEq(LitemallOrder::getUpdateTime, preUpdateTime);
        return query.updateSelective(order);
        //return orderMapper.updateWithOptimisticLocker(preUpdateTime, order);
    }

    public void deleteById(Integer id) {
    	LitemallOrder order = new LitemallOrder();
    	order.setId(id);
    	order.setDeleted(true);
    	litemallOrderDao.updateTemplateById(order);
        //litemallOrderMapper.logicalDeleteByPrimaryKey(id);
    }

    public int count() {
    	LitemallOrder order = new LitemallOrder();
    	order.setDeleted(false);
    	return (int)litemallOrderDao.templateCount(order);
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andDeletedEqualTo(false); return (int)
		 * litemallOrderMapper.countByExample(example);
		 */
    }

    public List<LitemallOrder> queryUnpaid(int minutes) {
    	
    	LitemallOrder order = new LitemallOrder();
    	order.setDeleted(false);
    	order.setOrderStatus(OrderUtil.STATUS_CREATE);
    	return litemallOrderDao.template(order);
    	
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andOrderStatusEqualTo(OrderUtil.STATUS_CREATE).andDeletedEqualTo
		 * (false); return litemallOrderMapper.selectByExample(example);
		 */
    }

    public List<LitemallOrder> queryUnconfirm(int days) {
    	 LocalDateTime now = LocalDateTime.now();
         LocalDateTime expired = now.minusDays(days);

        LambdaQuery<LitemallOrder> query = litemallOrderDao.createLambdaQuery();
        query.andEq(LitemallOrder::getOrderStatus, OrderUtil.STATUS_SHIP);
        query.andLess(LitemallOrder::getShipTime, expired);
        query.andEq(LitemallOrder::getDeleted, false);
        return query.select();
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andOrderStatusEqualTo(OrderUtil.STATUS_SHIP).andShipTimeLessThan
		 * (expired).andDeletedEqualTo(false); return
		 * litemallOrderMapper.selectByExample(example);
		 */
    }

    public LitemallOrder findBySn(String orderSn) {
    	LitemallOrder order = new LitemallOrder();
    	order.setOrderSn(orderSn);
    	order.setDeleted(false);
    	return litemallOrderDao.templateOne(order);
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andOrderSnEqualTo(orderSn).andDeletedEqualTo(false); return
		 * litemallOrderMapper.selectOneByExample(example);
		 */
    }

    public Map<Object, Object> orderInfo(Integer userId) {
    	
    	 LambdaQuery<LitemallOrder> query = litemallOrderDao.createLambdaQuery();
         query.andEq(LitemallOrder::getUserId, userId);
         query.andEq(LitemallOrder::getDeleted, false);
         List<LitemallOrder> orders =  query.select(LitemallOrder::getOrderStatus , LitemallOrder::getComments);
    	
			/*
			 * LitemallOrderExample example = new LitemallOrderExample();
			 * example.or().andUserIdEqualTo(userId).andDeletedEqualTo(false);
			 * List<LitemallOrder> orders =
			 * litemallOrderMapper.selectByExampleSelective(example,
			 * LitemallOrder.Column.orderStatus, LitemallOrder.Column.comments);
			 */
        int unpaid = 0;
        int unship = 0;
        int unrecv = 0;
        int uncomment = 0;
        for (LitemallOrder order : orders) {
            if (OrderUtil.isCreateStatus(order)) {
                unpaid++;
            } else if (OrderUtil.isPayStatus(order)) {
                unship++;
            } else if (OrderUtil.isShipStatus(order)) {
                unrecv++;
            } else if (OrderUtil.isConfirmStatus(order) || OrderUtil.isAutoConfirmStatus(order)) {
                uncomment += order.getComments();
            } else {
                // do nothing
            }
        }

        Map<Object, Object> orderInfo = new HashMap<Object, Object>();
        orderInfo.put("unpaid", unpaid);
        orderInfo.put("unship", unship);
        orderInfo.put("unrecv", unrecv);
        orderInfo.put("uncomment", uncomment);
        return orderInfo;

    }

    public List<LitemallOrder> queryComment(int days) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expired = now.minusDays(days);
        
        LambdaQuery<LitemallOrder> query = litemallOrderDao.createLambdaQuery();
        query.andGreat(LitemallOrder::getComments, (short) 0);
        query.andLess(LitemallOrder::getConfirmTime,expired);
        query.andEq(LitemallOrder::getDeleted, false);
        return query.select();
		/*
		 * LitemallOrderExample example = new LitemallOrderExample();
		 * example.or().andCommentsGreaterThan((short)
		 * 0).andConfirmTimeLessThan(expired).andDeletedEqualTo(false); return
		 * litemallOrderMapper.selectByExample(example);
		 */
    }

    public void updateAftersaleStatus(Integer orderId, Short statusReject) {
        LitemallOrder order = new LitemallOrder();
        order.setId(orderId);
        order.setAftersaleStatus(statusReject);
        order.setUpdateTime(LocalDateTime.now());
        litemallOrderDao.updateTemplateById(order);
       // litemallOrderMapper.updateByPrimaryKeySelective(order);
    }
}
